#include "routemanagerdialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QMessageBox>
#include <QInputDialog>
#include <QProcess>
#include <QDebug>
#include "routeeditdialog.h"
#include <QNetworkInterface>
#include <PolkitQt1/Authority>
#include <polkitqt1-subject.h>
#include <QHostAddress>
#include <QInputDialog>
#include <QMessageBox>
#include <QDebug>
#include <QRegularExpression>
#include <QProcessEnvironment>
#include <QSet>
#include <QFile>
#include <QTextStream>

RouteManagerDialog::RouteManagerDialog(QWidget *parent) : QDialog(parent) {
    setWindowFlags((windowFlags() & ~Qt::WindowMaximizeButtonHint & ~Qt::WindowMinimizeButtonHint) | Qt::Dialog | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
    setupUi();
    setFixedSize(this->size());
    loadRoutes();
}

void RouteManagerDialog::setupUi() {
    setWindowTitle("全局路由管理");
    resize(700, 500);
    QFont normalFont("Microsoft YaHei UI", 10);
    this->setFont(normalFont);
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    tabWidget = new QTabWidget(this);
    // 静态路由Tab
    QWidget *staticTab = new QWidget(this);
    QVBoxLayout *staticLayout = new QVBoxLayout(staticTab);
    routeTable = new QTableWidget(0, 5, staticTab);
    routeTable->setFont(normalFont);
    routeTable->setHorizontalHeaderLabels({"目标网络", "网关", "出接口", "跃点数", "路由类型"});
    routeTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    routeTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    routeTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
    staticLayout->addWidget(routeTable);
    QHBoxLayout *btnLayout = new QHBoxLayout;
    btnAdd = new QPushButton("添加", staticTab);
    btnEdit = new QPushButton("编辑", staticTab);
    btnDelete = new QPushButton("删除", staticTab);
    btnRefresh = new QPushButton("刷新", staticTab);
    btnLayout->addWidget(btnAdd);
    btnLayout->addWidget(btnEdit);
    btnLayout->addWidget(btnDelete);
    btnLayout->addWidget(btnRefresh);
    btnLayout->addStretch();
    staticLayout->addLayout(btnLayout);
    staticTab->setLayout(staticLayout);
    tabWidget->addTab(staticTab, "静态路由");
    mainLayout->addWidget(tabWidget);
    envTipLabel = new QLabel("提示：静态路由可用于多出口分流、特定网段定向等高级需求。更改后立即生效。", this);
    envTipLabel->setStyleSheet("color:#888;font-size:10pt;margin-top:8px;");
    mainLayout->addWidget(envTipLabel);
    connect(btnAdd, &QPushButton::clicked, this, &RouteManagerDialog::onAddRoute);
    connect(btnEdit, &QPushButton::clicked, this, &RouteManagerDialog::onEditRoute);
    connect(btnDelete, &QPushButton::clicked, this, &RouteManagerDialog::onDeleteRoute);
    connect(btnRefresh, &QPushButton::clicked, this, &RouteManagerDialog::onRefresh);
    connect(routeTable, &QTableWidget::doubleClicked, this, &RouteManagerDialog::onEditRoute);
}

void RouteManagerDialog::loadRoutes() {
    routeList.clear();
    routeTable->setRowCount(0);
    QSet<QString> uniqueKeys;
    // 1. 读取所有接口
    QStringList ifaceList;
    for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
        if (iface.flags() & QNetworkInterface::IsUp && !(iface.flags() & QNetworkInterface::IsLoopBack))
            ifaceList << iface.humanReadableName();
    }
    // 2. 读取所有profile的永久路由
    for (const QString &iface : ifaceList) {
        QProcess proc;
        proc.start("nmcli", QStringList() << "-g" << "GENERAL.CONNECTION" << "device" << "show" << iface);
        proc.waitForFinished();
        QString profile = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
        if (profile.isEmpty() || profile == "--") continue;
        QProcess proc2;
        proc2.start("nmcli", QStringList() << "connection" << "show" << profile);
        proc2.waitForFinished();
        QString output = QString::fromUtf8(proc2.readAllStandardOutput());
        for (const QString &line : output.split('\n')) {
            if (line.startsWith("ipv4.routes:")) {
                QString routes = line.section(':',1).trimmed();
                for (const QString &r : routes.split(',', Qt::SkipEmptyParts)) {
                    QStringList parts = r.trimmed().split(' ');
                    // 只处理目标、网关（可选metric），忽略无效内容
                    if (parts.size() < 2 || !parts[0].contains('.') || !parts[1].contains('.')) continue;
                    RouteEntry entry;
                    entry.destination = parts[0];
                    entry.gateway = parts[1];
                    entry.iface = iface;
                    entry.metric = (parts.size() >= 3) ? parts[2].toInt() : -1;
                    entry.type = "永久";
                    QString key = entry.destination + ":" + entry.gateway + ":" + entry.iface;
                    if (!uniqueKeys.contains(key)) {
                        routeList.append(entry);
                        uniqueKeys.insert(key);
                    }
                }
            }
        }
        // 兼容ifcfg-rh: 读取route-<iface>文件
        QString routeFile = "/etc/sysconfig/network-scripts/route-" + iface;
        QFile f(routeFile);
        if (f.exists() && f.open(QIODevice::ReadOnly|QIODevice::Text)) {
            // 先收集所有变量
            QMap<QString, QString> addrMap, maskMap, gwMap, metricMap;
            QTextStream ts(&f);
            while (!ts.atEnd()) {
                QString line = ts.readLine().trimmed();
                if (line.startsWith("#") || line.isEmpty() || line.contains("{") || line.contains("}")) continue;
                if (line.startsWith("ADDRESS")) {
                    QString idx = line.mid(7,1);
                    addrMap[idx] = line.section('=',1).trimmed();
                } else if (line.startsWith("NETMASK")) {
                    QString idx = line.mid(7,1);
                    maskMap[idx] = line.section('=',1).trimmed();
                } else if (line.startsWith("GATEWAY")) {
                    QString idx = line.mid(7,1);
                    gwMap[idx] = line.section('=',1).trimmed();
                } else if (line.startsWith("METRIC")) {
                    QString idx = line.mid(6,1);
                    metricMap[idx] = line.section('=',1).trimmed();
                }
            }
            // 组装有效路由
            for (const QString &idx : addrMap.keys()) {
                if (!maskMap.contains(idx) || !gwMap.contains(idx)) continue;
                QString addr = addrMap[idx];
                QString mask = maskMap[idx];
                QString gw = gwMap[idx];
                QString metric = metricMap.value(idx, "");
                if (addr.isEmpty() || mask.isEmpty() || gw.isEmpty()) continue;
                RouteEntry entry;
                entry.destination = addr + "/" + QString::number(QHostAddress(mask).toIPv4Address() ? QHostAddress(mask).toString().count('.')*8 : 24);
                entry.gateway = gw;
                entry.iface = iface;
                entry.metric = metric.isEmpty() ? -1 : metric.toInt();
                entry.type = "永久";
                QString key = entry.destination + ":" + entry.gateway + ":" + entry.iface;
                if (!uniqueKeys.contains(key)) {
                    routeList.append(entry);
                    uniqueKeys.insert(key);
                }
            }
            f.close();
        }
    }
    // 3. 读取临时路由
    QProcess proc2;
    proc2.start("ip", QStringList() << "route" << "show");
    proc2.waitForFinished();
    QString output2 = QString::fromUtf8(proc2.readAllStandardOutput());
    QRegularExpression re(R"((\S+) via (\S+) dev (\S+)(?:.*metric (\d+))?.*)");
    for (const QString &line : output2.split('\n', Qt::SkipEmptyParts)) {
        QRegularExpressionMatch m = re.match(line);
        if (m.hasMatch()) {
            RouteEntry entry;
            entry.destination = m.captured(1);
            entry.gateway = m.captured(2);
            entry.iface = m.captured(3);
            entry.metric = m.captured(4).isEmpty() ? -1 : m.captured(4).toInt();
            entry.type = "临时";
            QString key = entry.destination + ":" + entry.gateway + ":" + entry.iface;
            if (!uniqueKeys.contains(key)) {
                routeList.append(entry);
                uniqueKeys.insert(key);
            }
        }
    }
    // 填充表格
    routeTable->setRowCount(routeList.size());
    for (int i = 0; i < routeList.size(); ++i) {
        const RouteEntry &e = routeList[i];
        routeTable->setItem(i, 0, new QTableWidgetItem(e.destination));
        routeTable->setItem(i, 1, new QTableWidgetItem(e.gateway));
        routeTable->setItem(i, 2, new QTableWidgetItem(e.iface));
        routeTable->setItem(i, 3, new QTableWidgetItem(e.metric < 0 ? "自动" : QString::number(e.metric)));
        routeTable->setItem(i, 4, new QTableWidgetItem(e.type));
    }
}

void RouteManagerDialog::onAddRoute() {
    RouteEntry entry;
    QStringList ifaceList;
    for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
        if (iface.flags() & QNetworkInterface::IsUp && !(iface.flags() & QNetworkInterface::IsLoopBack))
            ifaceList << iface.humanReadableName();
    }
    RouteEditDialog dlg(this);
    dlg.setRoute(entry, ifaceList); // 新增时为空
    if (dlg.exec() == QDialog::Accepted) {
        entry = dlg.getRoute();
        QString errMsg;
        if (!validateRoute(entry, errMsg, -1)) {
            QMessageBox::warning(this, "校验失败", errMsg);
            return;
        }
        saveRoute(entry, false);
        loadRoutes();
    }
}

void RouteManagerDialog::onEditRoute() {
    int row = routeTable->currentRow();
    if (row < 0 || row >= routeList.size()) return;
    RouteEntry entry = routeList[row];
    QStringList ifaceList;
    for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
        if (iface.flags() & QNetworkInterface::IsUp && !(iface.flags() & QNetworkInterface::IsLoopBack))
            ifaceList << iface.humanReadableName();
    }
    RouteEditDialog dlg(this);
    dlg.setRoute(entry, ifaceList);
    if (dlg.exec() == QDialog::Accepted) {
        RouteEntry newEntry = dlg.getRoute();
        QString errMsg;
        if (!validateRoute(newEntry, errMsg, row)) {
            QMessageBox::warning(this, "校验失败", errMsg);
            return;
        }
        // 先删后加
        if (entry.type == "永久") {
            // 获取profile
            QProcess proc;
            proc.start("nmcli", QStringList() << "-g" << "GENERAL.CONNECTION" << "device" << "show" << entry.iface);
            proc.waitForFinished();
            QString profile = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
            if (!profile.isEmpty() && profile != "--") {
                // 读取所有routes
                QProcess proc2;
                proc2.start("nmcli", QStringList() << "-g" << "ipv4.routes" << "connection" << "show" << profile);
                proc2.waitForFinished();
                QString routesStr = QString::fromUtf8(proc2.readAllStandardOutput()).trimmed();
                QStringList routes = routesStr.split(',', Qt::SkipEmptyParts);
                // 去掉要删除的那一条
                QString toRemove = entry.destination + " " + entry.gateway;
                if (entry.metric >= 0) toRemove += " " + QString::number(entry.metric);
                QStringList newRoutes;
                for (const QString &r : routes) {
                    if (r.trimmed() != toRemove) newRoutes << r.trimmed();
                }
                // 写回routes
                QProcess proc3;
                proc3.start("nmcli", QStringList() << "connection" << "modify" << profile << "ipv4.routes" << newRoutes.join(", "));
                proc3.waitForFinished();
                // 激活连接
                QProcess proc4;
                proc4.start("nmcli", QStringList() << "connection" << "up" << profile);
                proc4.waitForFinished();
            }
        } else {
            // 临时路由，直接用ip命令删除
        QStringList delArgs = {"route", "del", entry.destination, "via", entry.gateway, "dev", entry.iface};
        if (entry.metric >= 0) delArgs << "metric" << QString::number(entry.metric);
        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
        QProcess proc;
        proc.setProcessEnvironment(env);
        proc.start("pkexec", QStringList() << "ip" << delArgs);
        proc.waitForFinished();
        }
        // 2. 添加新路由
        if (newEntry.type == "永久") {
            // 获取profile
            QProcess proc;
            proc.start("nmcli", QStringList() << "-g" << "GENERAL.CONNECTION" << "device" << "show" << newEntry.iface);
            proc.waitForFinished();
            QString profile = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
            if (!profile.isEmpty() && profile != "--") {
                // 拼接路由
                QString dest = newEntry.destination;
                QString gw = newEntry.gateway;
                QString routeStr = dest + " " + gw;
                if (newEntry.metric >= 0) routeStr += " " + QString::number(newEntry.metric);
                // 追加新路由
                QProcess proc2;
                proc2.start("nmcli", QStringList() << "connection" << "modify" << profile << "+ipv4.routes" << routeStr);
                proc2.waitForFinished();
                // 激活连接
                QProcess proc3;
                proc3.start("nmcli", QStringList() << "connection" << "up" << profile);
                proc3.waitForFinished();
            }
        } else {
            // 临时路由
            QStringList args = {"route", "add", newEntry.destination, "via", newEntry.gateway, "dev", newEntry.iface};
            if (newEntry.metric >= 0) args << "metric" << QString::number(newEntry.metric);
            QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
            QProcess proc;
            proc.setProcessEnvironment(env);
            proc.start("pkexec", QStringList() << "ip" << args);
            proc.waitForFinished();
        }
        loadRoutes();
    }
}

void RouteManagerDialog::onDeleteRoute() {
    int row = routeTable->currentRow();
    if (row < 0 || row >= routeList.size()) return;
    RouteEntry entry = routeList[row];
    if (QMessageBox::question(this, "删除路由", QString("确定要删除路由 %1 via %2 吗？").arg(entry.destination, entry.gateway)) != QMessageBox::Yes) return;
    if (entry.type == "永久") {
        // 1. 获取接口对应的NetworkManager profile名
        QProcess proc;
        proc.start("nmcli", QStringList() << "-g" << "GENERAL.CONNECTION" << "device" << "show" << entry.iface);
        proc.waitForFinished();
        QString profile = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
        if (profile.isEmpty() || profile == "--") {
            QMessageBox::warning(this, "永久路由删除失败", "未找到接口" + entry.iface + "的NetworkManager配置文件，无法删除永久路由");
            return;
        }
        // 2. 读取所有routes
        QProcess proc2;
        proc2.start("nmcli", QStringList() << "-g" << "ipv4.routes" << "connection" << "show" << profile);
        proc2.waitForFinished();
        QString routesStr = QString::fromUtf8(proc2.readAllStandardOutput()).trimmed();
        QStringList routes = routesStr.split(',', Qt::SkipEmptyParts);
        // 3. 去掉要删除的那一条
        QString toRemove = entry.destination + " " + entry.gateway;
        if (entry.metric >= 0) toRemove += " " + QString::number(entry.metric);
        QStringList newRoutes;
        for (const QString &r : routes) {
            if (r.trimmed() != toRemove) newRoutes << r.trimmed();
        }
        // 4. 用nmcli写入（无需pkexec）
        QProcess proc3;
        proc3.start("nmcli", QStringList() << "connection" << "modify" << profile << "ipv4.routes" << newRoutes.join(", "));
        proc3.waitForFinished();
        QString err = QString::fromUtf8(proc3.readAllStandardError());
        if (!err.trimmed().isEmpty()) {
            QMessageBox::warning(this, "永久路由删除失败", err.trimmed());
            return;
        }
        // 5. 激活连接使路由生效（无需pkexec）
        QProcess proc4;
        proc4.start("nmcli", QStringList() << "connection" << "up" << profile);
        proc4.waitForFinished();
        QString err2 = QString::fromUtf8(proc4.readAllStandardError());
        if (!err2.trimmed().isEmpty()) {
            QMessageBox::warning(this, "永久路由激活失败", err2.trimmed());
        }
    } else {
        // 临时路由
    QStringList args = {"route", "del", entry.destination, "via", entry.gateway, "dev", entry.iface};
    if (entry.metric >= 0) args << "metric" << QString::number(entry.metric);
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    QProcess proc;
    proc.setProcessEnvironment(env);
    proc.start("pkexec", QStringList() << "ip" << args);
    proc.waitForFinished();
    }
    loadRoutes();
}

void RouteManagerDialog::onRefresh() {
    loadRoutes();
}

void RouteManagerDialog::saveRoute(const RouteEntry &entry, bool isEdit, int row) {
    if (entry.type == "永久") {
        // 1. 获取接口对应的NetworkManager profile名
        QProcess proc;
        proc.start("nmcli", QStringList() << "-g" << "GENERAL.CONNECTION" << "device" << "show" << entry.iface);
        proc.waitForFinished();
        QString profile = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
        if (profile.isEmpty() || profile == "--") {
            QMessageBox::warning(this, "永久路由失败", "未找到接口" + entry.iface + "的NetworkManager配置文件，无法写入永久路由");
            return;
        }
        // 2. 拼接路由格式：目标网段/掩码 网关 metric
        QString dest = entry.destination;
        QString gw = entry.gateway;
        QString routeStr = dest + " " + gw;
        if (entry.metric >= 0) routeStr += " " + QString::number(entry.metric);
        // 3. 用nmcli写入（无需pkexec）
        QProcess proc2;
        proc2.start("nmcli", QStringList() << "connection" << "modify" << profile << "+ipv4.routes" << routeStr);
        proc2.waitForFinished();
        QString err = QString::fromUtf8(proc2.readAllStandardError());
        if (!err.trimmed().isEmpty()) {
            QMessageBox::warning(this, "永久路由失败", err.trimmed());
            return;
        }
        // 4. 激活连接使路由生效（无需pkexec）
        QProcess proc3;
        proc3.start("nmcli", QStringList() << "connection" << "up" << profile);
        proc3.waitForFinished();
        QString err2 = QString::fromUtf8(proc3.readAllStandardError());
        if (!err2.trimmed().isEmpty()) {
            QMessageBox::warning(this, "永久路由激活失败", err2.trimmed());
        }
    } else {
        // 临时路由
        QStringList args = {"route", "add", entry.destination, "via", entry.gateway, "dev", entry.iface};
        if (entry.metric >= 0) args << "metric" << QString::number(entry.metric);
        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
        QProcess proc;
        proc.setProcessEnvironment(env);
        proc.start("pkexec", QStringList() << "ip" << args);
        proc.waitForFinished();
        QString err = QString::fromUtf8(proc.readAllStandardError());
        if (!err.trimmed().isEmpty()) {
            QMessageBox::warning(this, "添加路由失败", err.trimmed());
        }
    }
}

bool RouteManagerDialog::validateRoute(const RouteEntry &entry, QString &errMsg, int skipRow) const {
    // 目标网络校验
    QRegularExpression netRe(R"(^\d{1,3}(\.\d{1,3}){3}/\d{1,2}$)");
    if (!netRe.match(entry.destination).hasMatch()) {
        errMsg = "目标网络格式错误，应为如192.168.1.0/24";
        return false;
    }
    // 网关校验
    QRegularExpression ipRe(R"(^\d{1,3}(\.\d{1,3}){3}$)");
    if (!entry.gateway.isEmpty() && !ipRe.match(entry.gateway).hasMatch()) {
        errMsg = "网关格式错误，应为如192.168.1.1";
        return false;
    }
    // 接口校验
    if (entry.iface.isEmpty()) {
        errMsg = "出接口不能为空";
        return false;
    }
    // metric校验
    if (entry.metric < -1 || entry.metric > 4294967295) {
        errMsg = "跃点数范围应为0~4294967295";
        return false;
    }
    // 目标网络与网关不能相同
    if (!entry.gateway.isEmpty() && entry.destination.startsWith(entry.gateway)) {
        errMsg = "目标网络和网关不能相同";
        return false;
    }
    // 目标网络不能重复，编辑时跳过自己
    for (int i = 0; i < routeList.size(); ++i) {
        if (i == skipRow) continue;
        const RouteEntry &e = routeList[i];
        if (e.destination == entry.destination && e.iface == entry.iface) {
            errMsg = "已存在相同目标网络和接口的路由";
            return false;
        }
    }
    // 网关不能为本机任一IP
    for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
        for (const QNetworkAddressEntry &addr : iface.addressEntries()) {
            if (addr.ip().toString() == entry.gateway) {
                errMsg = "网关不能为本机自身IP地址";
                return false;
            }
        }
    }
    // 网关不能为回环、广播、保留地址
    QHostAddress gw(entry.gateway);
    if (gw.isNull() || gw == QHostAddress::LocalHost || gw == QHostAddress::Broadcast || gw == QHostAddress::Any) {
        errMsg = "网关地址无效（回环、广播或保留地址）";
        return false;
    }
    // 网关必须在本地接口网段
    bool gwReachable = false;
    for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) {
        for (const QNetworkAddressEntry &addr : iface.addressEntries()) {
            QHostAddress net = addr.ip();
            QHostAddress mask = addr.netmask();
            if (net.protocol() != QAbstractSocket::IPv4Protocol || mask.isNull()) continue;
            quint32 netVal = net.toIPv4Address() & mask.toIPv4Address();
            quint32 gwVal = gw.toIPv4Address() & mask.toIPv4Address();
            if (netVal == gwVal) {
                gwReachable = true;
                break;
            }
        }
        if (gwReachable) break;
    }
    if (!entry.gateway.isEmpty() && !gwReachable) {
        errMsg = "网关地址不在本地任一接口网段内，可能不可达";
        return false;
    }
    return true;
} 